import sys
import os
import time
import subprocess
from PyQt6.QtWidgets import (
    QApplication, QMainWindow, QSplitter, QTreeView, QTabWidget, QStatusBar, 
    QVBoxLayout, QWidget, QTextEdit, QGraphicsView, QGraphicsScene, QGraphicsRectItem,
    QToolBar, QMessageBox, QPushButton, QLabel, QMenu, 
    QInputDialog, QFileDialog, QDialog, QDialogButtonBox, QSizePolicy
)
from PyQt6.QtGui import (
    QIcon, QTextCharFormat, QColor, QFont, QPen, QBrush, QPainterPath, QFileSystemModel,
    QTextCursor, QPalette, QStandardItemModel, QStandardItem, QSyntaxHighlighter, 
    QRegularExpressionValidator, QAction, QPainter
)
from PyQt6.QtCore import (
    Qt, QRectF, QPointF, QModelIndex, QFileInfo, QSortFilterProxyModel,
    QRegularExpression, QTimer, QSize
)
import git
from git import Repo, GitCommandError, InvalidGitRepositoryError


from repo_explorer import RepoExplorer
from git_manager import GitManager
from status_dashboard import StatusDashboard
from history_graph import HistoryGraphWidget





# ===================== 代码编辑器和语法高亮 =====================
class PythonHighlighter(QSyntaxHighlighter):
    def __init__(self, document):
        super().__init__(document)
        self.rules = []
        
        # 设置高亮规则
        self.init_highlight_rules()
    
    def init_highlight_rules(self):
        # 关键字
        keywords = [
            "and", "as", "assert", "break", "class", "continue", 
            "def", "del", "elif", "else", "except", "finally", 
            "for", "from", "global", "if", "import", "in", "is", 
            "lambda", "nonlocal", "not", "or", "pass", "raise", 
            "return", "try", "while", "with", "yield", "None", 
            "True", "False"
        ]
        keyword_format = QTextCharFormat()
        keyword_format.setForeground(QColor("#569cd6"))  # 蓝色
        keyword_format.setFontWeight(QFont.Weight.Bold)
        self.rules.extend([(r'\b%s\b' % kw, keyword_format) for kw in keywords])
        
        # 类名
        class_format = QTextCharFormat()
        class_format.setForeground(QColor("#4ec9b0"))  # 青色
        class_format.setFontWeight(QFont.Weight.Bold)
        self.rules.append((r'\b[A-Z]\w*\b', class_format))
        
        # 字符串
        string_format = QTextCharFormat()
        string_format.setForeground(QColor("#d69d85"))  # 橙色
        self.rules.extend([
            ('".*?"', string_format),
            ("'.*?'", string_format)
        ])
        
        # 注释
        comment_format = QTextCharFormat()
        comment_format.setForeground(QColor("#57a64a"))  # 绿色
        self.rules.append(('#.*', comment_format))
        
        # 数字
        number_format = QTextCharFormat()
        number_format.setForeground(QColor("#b5cea8"))  # 浅绿色
        self.rules.append(('\\b[0-9]+\\b', number_format))
        
        # 函数名
        function_format = QTextCharFormat()
        function_format.setForeground(QColor("#dcdcaa"))  # 黄色
        self.rules.append(('\\b[a-zA-Z_][a-zA-Z0-9_]*(?=\\()', function_format))
    
    def highlightBlock(self, text):
        for pattern, format in self.rules:
            regex = QRegularExpression(pattern)
            match_iter = regex.globalMatch(text)
            while match_iter.hasNext():
                match = match_iter.next()
                self.setFormat(match.capturedStart(), match.capturedLength(), format)






# ===================== 主应用程序 =====================
class PyKraken(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyKraken - Python Git Client")
        self.setGeometry(100, 100, 1400, 800)
        self.setWindowIcon(QIcon("icon.png" if os.path.exists("icon.png") else ""))
        
        # Git管理器和当前仓库路径
        self.git_mgr = GitManager()
        self.current_repo_path = None
        
        # 初始化UI
        self.init_ui()
        
        # 定时器自动刷新
        self.refresh_timer = QTimer(self)
        self.refresh_timer.timeout.connect(self.refresh_repo_status)
        self.refresh_timer.start(5000)  # 每5秒刷新一次
    
    def init_ui(self):
        # 创建主工具栏
        self.create_toolbar()
        
        # 创建中央分割布局
        main_splitter = QSplitter(Qt.Orientation.Horizontal)
        
        # 左侧面板：仓库管理
        left_panel = QWidget()
        left_layout = QVBoxLayout()
        
        # 仓库浏览器
        self.repo_explorer = RepoExplorer(self)
        left_layout.addWidget(self.repo_explorer, 3)
        
        # 状态仪表盘
        self.status_dashboard = StatusDashboard(self)
        left_layout.addWidget(self.status_dashboard, 2)
        
        left_panel.setLayout(left_layout)
        
        # 中央面板：代码视图
        central_panel = QSplitter(Qt.Orientation.Vertical)
        
        # 代码编辑区
        self.code_tabs = QTabWidget()
        self.code_tabs.setTabsClosable(True)
        self.code_tabs.tabCloseRequested.connect(self.close_tab)
        
        # 提交历史视图
        self.history_graph = HistoryGraphWidget(self)
        
        central_panel.addWidget(self.code_tabs)
        central_panel.addWidget(self.history_graph)
        central_panel.setSizes([400, 300])
        
        # 添加面板到主分割器
        main_splitter.addWidget(left_panel)
        main_splitter.addWidget(central_panel)
        main_splitter.setSizes([300, 1100])
        
        self.setCentralWidget(main_splitter)
        
        # 状态栏
        self.statusBar().showMessage("就绪")
    
    def create_toolbar(self):
        toolbar = self.addToolBar("Main Toolbar")
        toolbar.setMovable(False)
        toolbar.setIconSize(QSize(32, 32))
        
        # 仓库操作
        open_action = QAction(QIcon.fromTheme("document-open"), "打开仓库", self)
        open_action.triggered.connect(self.open_repo)
        
        clone_action = QAction(QIcon.fromTheme("edit-download"), "克隆仓库", self)
        clone_action.triggered.connect(self.clone_repo)
        
        # 版本控制
        commit_action = QAction(QIcon.fromTheme("vcs-commit"), "提交", self)
        commit_action.triggered.connect(self.commit_changes)
        
        push_action = QAction(QIcon.fromTheme("vcs-push"), "推送", self)
        push_action.triggered.connect(self.push_to_remote)
        
        pull_action = QAction(QIcon.fromTheme("vcs-update"), "拉取", self)
        pull_action.triggered.connect(self.pull_from_remote)
        
        # 分支管理
        branch_action = QAction(QIcon.fromTheme("vcs-branch"), "分支", self)
        branch_action.triggered.connect(self.show_branch_menu)
        
        # 刷新
        refresh_action = QAction(QIcon.fromTheme("view-refresh"), "刷新", self)
        refresh_action.triggered.connect(self.refresh_repo_status)
        
        # 添加到工具栏
        toolbar.addAction(open_action)
        toolbar.addAction(clone_action)
        toolbar.addSeparator()
        toolbar.addAction(commit_action)
        toolbar.addAction(push_action)
        toolbar.addAction(pull_action)
        toolbar.addSeparator()
        toolbar.addAction(branch_action)
        toolbar.addSeparator()
        toolbar.addAction(refresh_action)
    
    def open_repo(self):
        from PyQt6.QtWidgets import QFileDialog
        
        repo_path = QFileDialog.getExistingDirectory(self, "选择Git仓库")
        if repo_path:
            success, message = self.git_mgr.open_repo(repo_path)
            if success:
                self.current_repo_path = repo_path
                self.repo_explorer.load_repo(repo_path)
                self.refresh_repo_status()
                self.statusBar().showMessage(f"已打开仓库: {repo_path}")
            else:
                QMessageBox.warning(self, "打开仓库错误", message)
    
    def clone_repo(self):
        url, ok = QInputDialog.getText(self, "克隆仓库", "输入Git仓库URL:")
        if ok and url:
            path = QFileDialog.getExistingDirectory(self, "选择克隆位置")
            if path:
                # 创建子目录
                repo_name = url.split("/")[-1].replace(".git", "")
                target_path = os.path.join(path, repo_name)
                
                # 执行克隆
                success, message = self.git_mgr.clone_repo(url, target_path)
                if success:
                    self.current_repo_path = target_path
                    self.repo_explorer.load_repo(target_path)
                    self.refresh_repo_status()
                    self.statusBar().showMessage(f"已克隆仓库到: {target_path}")
                else:
                    QMessageBox.warning(self, "克隆错误", message)
    
    def refresh_repo_status(self):
        if not self.current_repo_path:
            return
        
        # 刷新分支信息
        self.status_dashboard.update_branch(self.git_mgr.current_branch)
        
        # 刷新状态信息
        status = self.git_mgr.get_status()
        self.status_dashboard.update_status(status)
        
        # 刷新历史图
        history_data = self.git_mgr.visualize_history()
        self.history_graph.draw_history(history_data)
    
    def commit_changes(self):
        if not self.current_repo_path:
            QMessageBox.warning(self, "提交", "请先打开一个Git仓库")
            return
        
        # 创建提交对话框
        from PyQt6.QtWidgets import QDialog, QDialogButtonBox
        
        class CommitDialog(QDialog):
            def __init__(self, files, parent=None):
                super().__init__(parent)
                self.setWindowTitle("提交更改")
                layout = QVBoxLayout()
                
                # 提交信息输入框
                self.message_edit = QTextEdit()
                self.message_edit.setPlaceholderText("输入提交信息...")
                self.message_edit.setMinimumHeight(100)
                layout.addWidget(QLabel("提交信息:"))
                layout.addWidget(self.message_edit)
                
                # 文件列表
                layout.addWidget(QLabel("已暂存的文件:"))
                files_list = QTextEdit()
                files_list.setReadOnly(True)
                files_list.setText("\n".join(files))
                files_list.setMaximumHeight(150)
                layout.addWidget(files_list)
                
                # 按钮
                button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | 
                                             QDialogButtonBox.StandardButton.Cancel)
                button_box.accepted.connect(self.accept)
                button_box.rejected.connect(self.reject)
                layout.addWidget(button_box)
                
                self.setLayout(layout)
            
            def get_commit_message(self):
                return self.message_edit.toPlainText().strip()
        
        # 获取已暂存的文件
        status = self.git_mgr.get_status()
        staged_files = status['staged']
        
        if not staged_files:
            QMessageBox.warning(self, "提交", "没有文件已暂存，请先暂存更改。")
            return
        
        dialog = CommitDialog(staged_files, self)
        if dialog.exec() == QDialog.DialogCode.Accepted:
            message = dialog.get_commit_message()
            if not message:
                QMessageBox.warning(self, "提交", "提交信息不能为空")
                return
            
            success, msg = self.git_mgr.commit(message)
            if success:
                self.statusBar().showMessage(msg)
                self.refresh_repo_status()
            else:
                QMessageBox.warning(self, "提交错误", msg)
    
    def push_to_remote(self):
        if not self.current_repo_path:
            QMessageBox.warning(self, "推送", "请先打开一个Git仓库")
            return
        
        success, msg = self.git_mgr.push()
        if success:
            self.statusBar().showMessage(msg)
        else:
            QMessageBox.warning(self, "推送错误", msg)
    
    def pull_from_remote(self):
        if not self.current_repo_path:
            QMessageBox.warning(self, "拉取", "请先打开一个Git仓库")
            return
        
        success, msg = self.git_mgr.pull()
        if success:
            self.statusBar().showMessage(msg)
            self.refresh_repo_status()
        else:
            QMessageBox.warning(self, "拉取错误", msg)
    
    def show_branch_menu(self):
        if not self.current_repo_path:
            QMessageBox.warning(self, "分支", "请先打开一个Git仓库")
            return
        
        branches = self.git_mgr.get_branches()
        if not branches:
            return
        
        menu = QMenu(self)
        
        # 添加分支切换项
        for branch in branches:
            action = menu.addAction(branch)
            action.triggered.connect(lambda checked, b=branch: self.switch_branch(b))
        
        # 添加创建新分支项
        menu.addSeparator()
        new_branch_action = menu.addAction("新建分支...")
        new_branch_action.triggered.connect(self.create_new_branch)
        
        # 显示菜单
        menu.exec(self.mapToGlobal(self.toolbar_position()))
    
    def toolbar_position(self):
        return QPoint(50, self.toolbar().height() + 5)
    
    def switch_branch(self, branch_name):
        if branch_name != self.git_mgr.current_branch:
            success, msg = self.git_mgr.checkout(branch_name)
            if success:
                self.statusBar().showMessage(msg)
                self.refresh_repo_status()
            else:
                QMessageBox.warning(self, "切换分支错误", msg)
    
    def create_new_branch(self):
        branch_name, ok = QInputDialog.getText(self, "新建分支", "输入新分支名称:")
        if ok and branch_name:
            if branch_name in self.git_mgr.get_branches():
                QMessageBox.warning(self, "创建分支", f"分支 '{branch_name}' 已存在")
                return
            
            success, msg = self.git_mgr.checkout(branch_name)
            if success:
                self.statusBar().showMessage(msg)
                self.refresh_repo_status()
            else:
                QMessageBox.warning(self, "创建分支错误", msg)
    
    def open_file_in_editor(self, file_path):
        # 检查是否已在打开的文件中
        for i in range(self.code_tabs.count()):
            if self.code_tabs.tabText(i) == QFileInfo(file_path).fileName():
                self.code_tabs.setCurrentIndex(i)
                return
        
        # 打开新标签页
        editor = CodeEditor()
        if editor.open_file(file_path):
            tab_name = QFileInfo(file_path).fileName()
            self.code_tabs.addTab(editor, tab_name)
            self.code_tabs.setCurrentWidget(editor)
    
    def close_tab(self, index):
        self.code_tabs.removeTab(index)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    
    # 设置应用程序样式
    app.setStyle("Fusion")
    
    # 自定义深色调色板
    palette = QPalette()
    palette.setColor(QPalette.ColorRole.Window, QColor("#1e1e1e"))
    palette.setColor(QPalette.ColorRole.WindowText, QColor("#d4d4d4"))
    palette.setColor(QPalette.ColorRole.Base, QColor("#252526"))
    palette.setColor(QPalette.ColorRole.AlternateBase, QColor("#2d2d30"))
    palette.setColor(QPalette.ColorRole.Text, QColor("#d4d4d4"))
    palette.setColor(QPalette.ColorRole.Button, QColor("#333333"))
    palette.setColor(QPalette.ColorRole.ButtonText, QColor("#d4d4d4"))
    palette.setColor(QPalette.ColorRole.Highlight, QColor("#007acc"))
    palette.setColor(QPalette.ColorRole.HighlightedText, Qt.GlobalColor.white)
    app.setPalette(palette)
    
    # 创建并显示主窗口
    window = PyKraken()
    window.show()
    
    sys.exit(app.exec())